/*
 * AS3 MultiTouch Client
 *
 * TouchEventSimulatorProvider - Simulate a Touch Interface with mouse and keyboard  
 *
 * Copyright 2008 Artifacts - Fine Software Development
 * http://www.artifacts.de
 * Author: Michael Markowski (m.markowski@artifacts.de)
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
 
/**
 * SMKTouchEventProvider - Connectes to a socket and translates incoming SMK Events
 * 
 */ 
 
package de.artifacts.multitouch
{
	import flash.display.DisplayObjectContainer;
	import flash.events.*;
	import flash.geom.Point;
	import flash.net.Socket;
	import flash.utils.ByteArray;
	import flash.utils.Dictionary;
	import net.contentismissing.tlabs.cocktailparty.InfoEvent;
	import mx.core.Application;
	
	public class SMKTouchEventProvider implements ITouchEventProvider
	{		
		public var touchManager : TouchManager; // set via ioc by touchManager
		private var selectedCursor : Cursor;
		private var activeCursors : Dictionary;

		public var serverIP : String;		
		public var serverPort : int;
		public var log : String;
		public var socket : Socket;
		private var zero : ByteArray;
		private var response:String;
		
		public static const cursorOffsetX : Number = 0;
		public static const cursorOffsetY : Number = 0;
		
		public static const SENSOR_CONNECT : int = 1;
		public static const CURSOR_CREATE : int = 2;
		public static const CURSOR_DOWN : int = 3;
		public static const CURSOR_MOVE : int = 4;
		public static const CURSOR_UP : int = 5;
		public static const CURSOR_DESTROY : int = 6;
		public static const SENSOR_DISCONNECT : int = 7;
		
		public function SMKTouchEventProvider(container : DisplayObjectContainer)
		{	
			this.touchManager = touchManager;	
			this.activeCursors = new Dictionary();
			
			zero = new ByteArray();
			zero.writeByte(0x00);
			serverIP = "127.0.0.1"
			serverPort = 6682;
			socket = new Socket();			
			configureListeners(socket);
			socket.connect(serverIP, serverPort);
			log = new String();
			
		}

		public function setTouchManager(manager : TouchManager) : void
		{
			this.touchManager = manager;	
		}
		
		private function configureListeners(dispatcher:IEventDispatcher):void {
            dispatcher.addEventListener(Event.CLOSE, closeHandler);
            dispatcher.addEventListener(Event.CONNECT, connectHandler);
            dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
            dispatcher.addEventListener(ProgressEvent.SOCKET_DATA, dataHandler);
            dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
        }

        private function closeHandler(event:Event):void {
			var evt : InfoEvent = new InfoEvent(InfoEvent.kFatal);
			evt.message = "FATAL: SMK disconnected. Please restart.";
			Application.application.dispatchEvent(evt);            			                        
        }

        private function connectHandler(event:Event):void {
            trace("connectHandler: " + event);
        }

        private function dataHandler(event:ProgressEvent):void {            
        	readResponse();
        }

	    private function readResponse():void {
	    	
	        var str:String = socket.readUTFBytes(socket.bytesAvailable);
	        var strArray : Array = str.split("\n");
	        var s : String;
	        var xml : XML;
	        var eventType : int;
	        var cursorId : int;
	        var cursorX : int;
	        var cursorY : int;
	        var cursorClickNumber : int;
	        var eventParts : Array;	 
	               
	        for (var i:int=0; i<strArray.length; i++)
	        {
	        	try
	        	{
		        	s = strArray[i];	        	
		        	eventParts = s.split(",");
		        	eventType = eventParts[0];   	
		        	cursorId = parseInt(eventParts[1]);
					switch (eventType)
					{
						case SENSOR_CONNECT:
						break;
		 				case CURSOR_CREATE:
							if (touchManager==null) return;
							selectedCursor = touchManager.createCursor(cursorId);
							activeCursors[cursorId] = selectedCursor;
						break;
						case CURSOR_DOWN:
							cursorX = parseInt(eventParts[2]) + cursorOffsetX;
							cursorY = parseInt(eventParts[3]) + cursorOffsetY;
							cursorClickNumber = parseInt(eventParts[4]);
							if (touchManager==null) return;							
							touchManager.cursorDown(cursorX, cursorY, cursorId, cursorClickNumber);
						break;
						case CURSOR_MOVE:
							cursorX = parseInt(eventParts[2]) + cursorOffsetX;
							cursorY = parseInt(eventParts[3]) + cursorOffsetY;
							selectedCursor = activeCursors[cursorId];
							if (selectedCursor==null || touchManager==null) return;
							selectedCursor.position = new Point(cursorX, cursorY);
							touchManager.cursorMoved(selectedCursor);
						break;
						case CURSOR_UP:
							if (touchManager==null) return;							
							cursorX = parseInt(eventParts[2]) + cursorOffsetX;
							cursorY = parseInt(eventParts[3]) + cursorOffsetY;
							touchManager.cursorUp(cursorX, cursorY, cursorId);								
						break;
						case CURSOR_DESTROY:
							if (touchManager==null) return;
							touchManager.removeCursor(cursorId);
							activeCursors[cursorId] = null;								
							delete activeCursors[cursorId];					
						break;
						case SENSOR_DISCONNECT:
							var evt : InfoEvent = new InfoEvent(InfoEvent.kFatal);
							evt.message = "FATAL: SMK disconnected. Please restart.";
							Application.application.dispatchEvent(evt);            			                        						
						break;
						default:
						break;						
					}										
	        	} catch (err : Error) { }	
	        }
	        socket.flush();	        	       
	    }
    
        private function ioErrorHandler(event:IOErrorEvent):void {
            trace("ioErrorHandler: " + event);
			var evt : InfoEvent = new InfoEvent(InfoEvent.kFatal);
			evt.message = "FATAL: Connection to SMK failed. Please restart.";
			Application.application.dispatchEvent(evt);            			                        
        }

        private function progressHandler(event:ProgressEvent):void {
            trace("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
        }

        private function securityErrorHandler(event:SecurityErrorEvent):void {
            trace("securityErrorHandler: " + event);
			var evt : InfoEvent = new InfoEvent(InfoEvent.kFatal);
			evt.message = "FATAL: Connection to SMK failed. Flash security error. Please restart.";
			Application.application.dispatchEvent(evt);            			                        
        }

	}
}